import java.io.*;
import java.util.*;
import java.util.ArrayList;
import java.io.PrintWriter;
import java.io.FileWriter;
import java.io.FileReader;


public class StudentRegistrationSystem  {

  private UserDatabase usersDB;
  private StudentCourseTable StudentCourseDB;
  private CourseDatabase courseDB;
  private ArrayList<Course> courseList;

  public StudentRegistrationSystem() {
	  usersDB = new UserDatabase();
	  StudentCourseDB = new StudentCourseTable(usersDB);
	  courseDB = new CourseDatabase();
	  courseList = courseDB.getAvailableCourses();
 }

  public String getStudentID(String userID) {
	  Student std = usersDB.GetStudentByUsrId(userID);
	  return std.iD();
  }
//add a new student profile given a set of data
  public boolean addNewStudent(Student stuObj, String password) {
	  addLoginCredentials(stuObj.userId(), password);
	  StudentCourseDB.AddStudent(stuObj.iD());
	  return usersDB.AddStudent(stuObj);

  }
  //edit or update an existing student profile given a student id and set of data
  public boolean updateStudent(Student stuObj) {
		int allrecords = 18;
		StudentTableIndices[] enFieldsChanged = StudentCourseDB.AllStudentTableIndices();
	return usersDB.UpdateStudent(stuObj, enFieldsChanged, allrecords);
  }

//get all of the student profile data(or the login can return a student object) so the ui can display profile info
  public Student getStudent(String userID) {
	  Student std = usersDB.GetStudentByUsrId(userID);
	  if (std == null) {
		  System.out.println("Student Record does not exists!!!");
	  }
	  return std;
  }

//register a course to a student given a student and a course
  public boolean registerCourse(String studentID, String courseID) {
	   Course course = courseDB.getCourseById(courseID);
	   //System.out.println("CourseId " + courseID);
	   //System.out.println(course.toString());
	   boolean retVal = false;
	   if (course.getNCurrentEnrol() < course.getEnrollmentLimit()) {
 	   		retVal = StudentCourseDB.RegisterStudentToCourse(usersDB,studentID,courseID);
 	   		if (retVal)
 	   			return courseDB.AddStudent(courseID);
 	   		//course.setNCurrentEnrol(course.getNCurrentEnrol()+1);
 	   		//we don't have a method to update a course in the DB.
 	   		//its not explicitly required to update the number of enrolled students, only to not allow a student to register to a course that is full.
		}
		return retVal;
  }

//method to unregister a course given a student and course id
  public boolean unRegsiterCourse(String studentID, String courseID) {
		Course course = courseDB.getCourseById(courseID);
		boolean retVal = false;
		retVal = StudentCourseDB.DropCourseForStudent(usersDB,studentID,courseID);
		if (retVal)
			return courseDB.DropStudent(courseID);

		return retVal;
  }

//method to return the list of available courses
	public ArrayList<Course> getAvailableCourses() {
			return courseDB.getAvailableCourses();
	}

/*method to return the list of registered courses given a student id*/
//this requires a StudentCourseDB
	public List<String> getRegisteredCourses(String StudentID) {
		return StudentCourseDB.getRegisteredCourseList(StudentID);
	}

  //TODO: need to add the userId and password to the loginDB
  public boolean addLoginCredentials (String userId, String userPassword) {
	  	boolean retVal = false;
	  	try {
			PrintWriter f0 = new PrintWriter(new FileWriter("loginDB.csv", true));
    		f0.println(userId+","+ userPassword);
			f0.close();
			retVal = true;
		} catch (IOException e) {
  			e.printStackTrace();
  			retVal = false;
		}
		return retVal;
  }

  public void Close() {
		usersDB.CloseDatabase();
		StudentCourseDB.CloseDatabase();
		courseDB.CloseDatabase();
  }

  // Validate user login information - text file is username, then password
  public boolean validateLoginCredentials (String userId, String userPassword) {
		File userLoginFile;
		Scanner fileScanner;
		boolean PasswordValid=false;

		try {
			userLoginFile  = new File("loginDB.csv"); //need to replace with actual filename
			fileScanner = new Scanner(userLoginFile);

			while (fileScanner.hasNextLine())
			{
				String[] personAttributes = fileScanner.nextLine().split(",");
				//System.out.printf("Username: (%s), password: (%s)\n",personAttributes[0].trim(), personAttributes[1].trim() );
				if((userId.equals(personAttributes[0].trim()) == true) && (userPassword.equals(personAttributes[1].trim())==true))
				{
				   PasswordValid=true;
				   //System.out.println("Validated password");
				   break;
				}
			}
			fileScanner.close();
		} catch (FileNotFoundException e) {
  			e.printStackTrace();
		}
		if (!PasswordValid)
		{
			System.out.println("Please check user name and password and retry: ");
		}
		else
		{
			//System.out.printf("userId (%s) pass(%s)\n", userId, userPassword);
			if(usersDB.GetStudentByUsrId(userId) == null) {
				PasswordValid = false;  //no student record, so login fails.
				System.out.printf("Did not find Student Record for userId %s\n", userId);
			}
		}
		return PasswordValid;

}
public boolean changeLoginCredentials (String strOldUserName, String strOldPassword,String strNewUserName, String strNewPassword) {
  		//Read loginDB file and save into array
  		File userLoginFile;
  		Scanner fileScanner;
  		List<String> list = new ArrayList<String>();
  		boolean PasswordChanged=false;
		String userChange = strOldUserName+","+strOldPassword;
  		try {
  			userLoginFile  = new File("loginDB.csv");
  			fileScanner = new Scanner(userLoginFile);

  			while (fileScanner.hasNextLine()){
  				String userInfo = fileScanner.nextLine();
  				if(userInfo.equals(userChange) == true){
  				   list.add(strNewUserName+","+strNewPassword);
  				   PasswordChanged=true;
  				}
  				else{
					list.add(userInfo);
				  }
  			}
  			fileScanner.close();

		//write to file
		File testFile;
		PrintWriter outFile;

		try {
			testFile = new File("loginDB.csv");
			outFile = new PrintWriter(testFile);
			for (String element : list){
				outFile.println(element);
				}
				outFile.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
  		} catch (FileNotFoundException e) {
    			e.printStackTrace();
  		}
  		return PasswordChanged;
  }

}